/*!
\copyright  Copyright (c) 2019 Qualcomm Technologies International, Ltd.\n
            All Rights Reserved.\n
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\version    
\file       
\brief      Generic interface to topology procedure handling.

This module defines the interface for a topology Procedure.

A Procedure is the code that implements how a topology Goal acts on the system
to achieve that Goal. It can be a simple synchronous operation to enable or
disable a feature or it could be a longer-running asynchronous operation, for
example connecting a handset.

The interface below has two main parts:
* An interface to start or cancel a Procedure that the Procedure must implement
* An interface that the Procedure uses to tell the goals engine that about its
  status. It must use this interface to allow the goal engine to track the
  progress of the goal.

A Procedure should be implemented so that it does one task, or perhaps closely
related tasks, only. If more complex behaviour is required for a Goal the
script engine provides a way to put multiple procedures into a list. Using this
the topology can build up more complex tasks from a group of simple Procedures.

*/

#ifndef PROCEDURES_H
#define PROCEDURES_H

#include <message.h>


/*! Type for the procedure id. */
typedef uint16 procedure_id;

/*! Highest supported procedure id. */
#define PROCEDURE_ID_MAX (0xFF) /* 255 */

/*! Result values returned when a procedure completes. */
typedef enum
{
    /*! Procedure succeeded. */
    procedure_result_success,

    /*! Procedure failed. */
    procedure_result_failed,

    /*! Procedure timed out before success or failure determined. */
    procedure_result_timeout,
} procedure_result_t;

/*! Callback used by procedure to indicate it has started.

    If the result is not a success status then the goal engine will treat this
    as an error with the Procedure.

    \param[in] proc Id of the Procedure that has started.
    \param[in] result Start status.
*/
typedef void (*procedure_start_cfm_func_t)(procedure_id proc, procedure_result_t result);

/*! Callback used by procedure to indicate it has completed.

    If the Procedure is an asynchronous operation this should be called only
    when the Procedure is complete.

    \param[in] proc Id of the Procedure that has started.
    \param[in] result Completion status.
*/
typedef void (*procedure_complete_func_t)(procedure_id proc, procedure_result_t result);

/*! Callback used by procedure to indicate cancellation has completed.

    If cancellation is an asynchronous operation this should be called only
    when cancellation is complete.

    \param[in] proc Id of the Procedure that has started.
    \param[in] result Cancellation status.
*/
typedef void (*procedure_cancel_cfm_func_t)(procedure_id proc, procedure_result_t result);

/*! Definition of common procedure start function.

    \param[in] task The Task to send messages generated by this Procedure.
    \param[in] start_fn The function to call to confirm the Procedure has
                        started.
    \param[in] comp_fn The function to call to confirm the Procedure has
                       completed.
    \param[in] goal_data Custom data for this Procedure.
*/
typedef void (*procedure_start_func_t)(Task result_task,
                                       procedure_start_cfm_func_t start_fn,
                                       procedure_complete_func_t comp_fn,
                                       Message goal_data);

/*! Definition of common procedure cancellation function.

    \param[in] cancel_fn The function to call to confirm the Procedure has been
                         cancelled
*/
typedef void (*procedure_cancel_func_t)(procedure_cancel_cfm_func_t cancel_fn);

/*! Definition of a generic topology procedure */
typedef struct
{
    /*! Function that is called to start the procedure. */
    const procedure_start_func_t    proc_start_fn;

    /*! Function that is called to cancel the procedure. */
    const procedure_cancel_func_t   proc_cancel_fn;
} procedure_fns_t;


/*! \brief Send a delayed start confirmation.

    If a Procedure needs to complete within its start function it must
    use this delayed complete confirm instead.

    \note Currently it is not possible to call the #procedure_complete_func_t
    callback directly from the #procedure_start_func_t due to the way that Goal
    completion can allow queued goals to run immediately.

    \param complete_fn The complete function that was passed in to the
                       Procedure #procedure_start_func_t
    \param proc Id of the Procedure that has completed
    \param result Completion status
*/
void Procedures_DelayedCompleteCfmCallback(procedure_complete_func_t complete_fn,
                                           procedure_id proc, procedure_result_t result);

/*! \brief Send a delayed cancel confirmation.

    If a Procedure needs to call the cancel confirm function within its cancel
    function it must use this delayed cancel confirm instead.

    \note Currently it is not possible to call the #procedure_cancel_cfm_func_t
    callback directly from the #procedure_cancel_func_t due to the way that
    Goal completion can allow queued goals to run immediately.

    \param cancel_fn The cancel function that was passed in to the
                     Procedure #procedure_cancel_func_t
    \param proc Id of the Procedure that has been cancelled
    \param result Cancellation status
*/
void Procedures_DelayedCancelCfmCallback(procedure_cancel_cfm_func_t cancel_fn,
                                         procedure_id proc, procedure_result_t result);

#endif /* PROCEDURES_H */
